'''
Description: 
Author: Zilu
Date: 2021-11-12 15:26:13
Version: 
LastEditTime: 2021-11-12 15:47:15
LastEditors: Zilu
'''

# 前面提到过使用with语句可以方便地使用文件资源
# 正确实现了上下文管理的对象（__enter__, __exit__），都可以使用使用with语句
class Query(object):
    def __init__(self, name) -> None:
        super().__init__()
        self.name = name

    def __enter__(self):
        print('Begin')
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        if exc_type:
            print('Error')
        else:
            print('End')

    def query(self):
        print('Query info about %s...' % self.name)

with Query('Bob') as q:
    q.query()

# 使用contextmanager修饰器更为方便
from contextlib import contextmanager
class Query(object):
    def __init__(self, name) -> None:
        super().__init__()
        self.name = name

    def query(self):
        print('Query info about %s...' % self.name)

@contextmanager
def createQuery(name):
    print('Begin')
    q = Query(name)
    yield q
    print('End')

# @contextmanager修饰器接受一个generator，用yield结合with...as var将变量输出出去
with createQuery('Alice') as q:
    q.query()

# 代码的执行顺序是：
# with语句首先执行yield之前的语句
# yield调用会执行with语句内部的所有语句
# 最后执行yield之后的语句

# 如果一个对象没有实现上下文，就不能用于with语句，
# 但是可以用closing()将对象变成上下文对象
from contextlib import closing
from urllib.request import urlopen

with closing(urlopen('https://www.python.org')) as page:
    for line in page:
        print(line)

# closing也是一个经过@contextmanager装饰的generator，这个generator编写起来其实非常简单：
@contextmanager
def closing(thing):
    try:
        yield thing
    finally:
        thing.close()



